/*
	* Created by : Varun Tyagi
	*
	* This sample tutorial explains the working of audio in SDL.
	* SDL's internal audio is not much of user friendly, this is why we will be using an audio library called SDL_Mixer.
*/

/* Include library files. */
#include "SDL.h"
#include "SDL_image.h"
#include "SDL_ttf.h"
#include "SDL_mixer.h"
#include <string>

/* Screen attributes. */
const int SCREEN_WIDHT = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

/* Surfaces. */
SDL_Surface *pBackground = nullptr;
SDL_Surface *pMessage = nullptr;
SDL_Surface *pScreen = nullptr;

/* The event structure. */
SDL_Event event;

/* The font. */
TTF_Font *pFont = nullptr;

/* The text color. */
SDL_Color textColor = { 1, 0, 0 };

/* The music that will be played. */
Mix_Music *pMusic = nullptr;

/* The sound effect that will be used. */
Mix_Chunk *pScratch = nullptr;
Mix_Chunk *pHigh =  nullptr;
Mix_Chunk *pMid = nullptr;
Mix_Chunk *pLow = nullptr;

/* Image loader. */
SDL_Surface *load_image( std::string filename )
{
	/* The image that we want to load. */
	SDL_Surface *pLoadedImage = nullptr;

	/* Optimized image. */
	SDL_Surface *pOptimizedImage = nullptr;

	/* Load the image. */
	pLoadedImage = IMG_Load( filename.c_str() );

	/* Check to see if we have loaded it correctly. */
	if( nullptr != pLoadedImage )
	{
		/* Optimize it. */
		pOptimizedImage = SDL_DisplayFormat( pLoadedImage );

		/* Free the old image. */
		SDL_FreeSurface( pLoadedImage );

		/* If the surface is optimized. */
		if( nullptr != pOptimizedImage )
		{
			/* Color key surface. */
			SDL_SetColorKey( pOptimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( pOptimizedImage->format, 0, 0xFF, 0xFF) );
		}
	}

	/* Return the optimized image. */
	return pOptimizedImage;
}

/* Surface applier. */
void apply_surface( int x, int y, SDL_Surface *pSource, SDL_Surface *pDestination, SDL_Rect* pClip = nullptr )
{
	/* Holds offset. */
	SDL_Rect offset;

	/* Get offset. */
	offset.x = x;
	offset.y = y;

	/* Blit. */
	SDL_BlitSurface( pScreen, pClip, pDestination, &offset );
}

/* Init SDL. */
bool init_SDL( void )
{
	/* Initialize SDL. */
	if( -1 == SDL_Init( SDL_INIT_EVERYTHING ) )
	{
		return false;
	}

	/* Set up the screen. */
	pScreen = SDL_SetVideoMode( SCREEN_WIDHT, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

	/* Check the screen. */
	if( nullptr == pScreen )
	{
		return false;
	}

	/* Initialize SDL Ttf. */
	if( -1 == TTF_Init() )
	{
		return false;
	}

	/* Initialize SDL_mixer (Audio). */
	if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 )  == -1 )
	{
		return false;
	}

	/* Set window caption. */
	SDL_WM_SetCaption( "Monitor Sounds", nullptr );

	return true;
}

/* Load files. */
bool load_file( void )
{
	/* Load the background. */
	pBackground = load_image( "background.bmp" );

	/* Check the background. */
	if( nullptr == pBackground )
	{
		return false;
	}

	/* Open the font. */
	pFont = TTF_OpenFont( "lazy.ttf", 30 );

	/* Check the font. */
	if( nullptr ==  pFont )
	{
		return false;
	}

	/* Load the music. */
	pMusic = Mix_LoadMUS( "beat.wav" );

	/* Check the loaded music. */
	if( nullptr == pMusic )
	{
		return false;
	}

	/* Load the sound effects. */
	pScratch	= Mix_LoadWAV( "scratch.wav" );
	pHigh		= Mix_LoadWAV( "high.wav" );
	pMid		= Mix_LoadWAV( "medium.wav" );
	pLow		= Mix_LoadWAV( "low.wav" );
	
	/* Check for loaded files. */
	if( (pScratch == nullptr) || (pHigh == nullptr) || (pMid == nullptr) || (pLow == nullptr) )
	{
		return false;
	}

	/* If everything went well return. */
	return true;
}

/* Clean up. */
void clean_SDL( void )
{
	/* Free the surface. */
	SDL_FreeSurface( pBackground );

	/* Free audio stuff. */
	Mix_FreeChunk( pScratch );
	Mix_FreeChunk( pHigh );
	Mix_FreeChunk( pMid );
	Mix_FreeChunk( pLow );

	/* Free the music. */
	Mix_FreeMusic( pMusic );

	/* Close the font. */
	TTF_CloseFont( pFont );

	/* QUIT SDL_mixer. */
	Mix_CloseAudio();

	/* Close the font. */
	TTF_Quit();

	/* QUIT SDL. */
	SDL_Quit();
}

/* Main. */
int main( int argc, char** argv )
{
	/* The quit flag. */
	bool bQuit = false;

	/* Initialize SDL. */
	if( false == init_SDL() )
	{
		return 1;
	}

	/* Load the files. */
	if( false == load_file() )
	{
		return 1;
	}

	/* Apply background. */
	apply_surface( 0, 0, pBackground, pScreen );

	/* Render text. */
	pMessage = TTF_RenderText_Solid( pFont, "Press 1, 2, 3 and 4 to play the different sound effects.", textColor );

	/* Check the message. */
	if( nullptr == pMessage )
	{
		return 1;
	}

	/* Show the message on the screen. */
	apply_surface( (SCREEN_WIDHT - pMessage->w) / 2, 100, pMessage, pScreen );

	/* Free the message. */
	SDL_FreeSurface( pMessage );

	/* Render next text. */
	pMessage = TTF_RenderText_Solid( pFont, "Press 9 to play and pause the music.", textColor );

	/* Check the message. */
	if( nullptr == pMessage )
	{
		return 1;
	}

	/* Show the message on the screen. */
	apply_surface( (SCREEN_WIDHT - pMessage->w) / 2, 200, pMessage, pScreen );

	/* Free the message. */
	SDL_FreeSurface( pMessage );

	/* Render the text. */
	pMessage = TTF_RenderText_Solid( pFont, "Press 0 to stop the music.", textColor );

	/* Check the message. */
	if( nullptr == pMessage )
	{
		return 1;
	}

	/* Show the message on the screen. */
	apply_surface( (SCREEN_WIDHT - pMessage->w) / 2, 300, pMessage, pScreen );

	/* Free the message. */
	SDL_FreeSurface( pMessage );

	/* Update the screen. */
	if( -1 == SDL_Flip( pScreen ) ) 
	{
		return 1;
	}

	/* While the user hasn't quit. */
	while( false == bQuit )
	{
		/* While there is event to handle. */
		while( SDL_PollEvent( &event ) )
		{
			/* If the key is pressed. */
			if( SDL_KEYDOWN == event.type )
			{
				/* If 1 is pressed. */
				if( event.key.keysym.sym == SDLK_1 )
				{
					/* Play the scratch effect. */
					if( Mix_PlayChannel( -1, pScratch, 0 ) == -1 ) 
					{
						return 1;
					}
				}

				/* If 2 is pressed. */
				if( event.key.keysym.sym == SDLK_2 )
				{
					/* Play the high hit effect. */
					if( Mix_PlayChannel( -1, pHigh, 0 ) == -1 )
					{
						return 1;
					}
				}

				/* If 3 is pressed. */
				if( event.key.keysym.sym == SDLK_3 )
				{
					/* Play the high hit effect. */
					if( Mix_PlayChannel( -1, pMid, 0 ) == -1 )
					{
						return 1;
					}
				}

				/* If 4 is pressed. */
				if( event.key.keysym.sym == SDLK_4 )
				{
					/* Play the high hit effect. */
					if( Mix_PlayChannel( -1, pLow, 0 ) == -1 )
					{
						return 1;
					}
				}

				/* If 9 is pressed. */
				if( event.key.keysym.sym == SDLK_9 )
				{
					/* Check to see if the music is already not being played. */
					if( Mix_PlayingMusic() == 0 )
					{
						/* Play the high hit effect. */
						if( Mix_PlayMusic( pMusic, -1 ) == -1 )
						{
							return 1;

						}
					}
					else /* The music is on. */
					{
						/* If the music is paused, resume it. */
						if( Mix_PausedMusic() == 1 )
						{
							/* Resume. */
							Mix_ResumeMusic();
						}
						else /* Pause the music. */
						{
							Mix_PauseMusic();
						}
					}
				}

				/* If 0 is pressed. */
				if( event.key.keysym.sym == SDLK_0 )
				{
					/* Stop the music. */
					Mix_HaltMusic();
				}
			}

			/* Check to see if the user has Xed out the window. */
			if( SDL_QUIT == event.type )
			{
				/* QUIT. */
				bQuit = true;
			}
		}
	}

	/* Clean up SDL. */
	clean_SDL();

	/* return true. */
	return 0;
}

